package com.termux.frontend.component

import java.util.concurrent.ConcurrentHashMap

/**
 * @author kiva
 */
object ComponentManager {
    private val COMPONENTS = ConcurrentHashMap<Class<out NeoComponent>, NeoComponent>()

    fun registerComponent(componentClass: Class<out NeoComponent>) {
        if (COMPONENTS.containsKey(componentClass)) {
            throw ComponentDuplicateException(componentClass.simpleName)
        }
        val component = createServiceInstance(componentClass)
        COMPONENTS.put(componentClass, component)
        component.onServiceInit()
    }

    fun unregisterComponent(componentInterface: Class<out NeoComponent>) {
        val component = COMPONENTS[componentInterface]
        if (component != null) {
            component.onServiceDestroy()
            COMPONENTS.remove(componentInterface)
        }
    }

    @Suppress("UNCHECKED_CAST")
    fun <T : NeoComponent> getComponent(componentInterface: Class<T>, errorThrow: Boolean = true) : T {
        val component: NeoComponent = COMPONENTS[componentInterface] ?:
                    throw ComponentNotFoundException(componentInterface.simpleName)

        component.onServiceObtained()
        return component as T
    }

    inline fun <reified T : NeoComponent> getComponent(): T {
        val componentInterface = T::class.java
        return getComponent(componentInterface);
    }

    private fun createServiceInstance(componentInterface: Class<out NeoComponent>): NeoComponent {
        return componentInterface.newInstance()
    }
}
